package com.somewater.game
{
	import com.greensock.TweenMax;
	import com.somewater.control.IClear;
	import com.somewater.controller.PopUpManager;
	import com.somewater.game.controllers.SocketHandler;
	import com.somewater.game.controllers.SpatialController;
	import com.somewater.game.display.Cup;
	import com.somewater.storage.Lib;
	import com.somewater.storage.RoomDef;
	
	import flash.display.DisplayObject;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.KeyboardEvent;
	import flash.utils.getTimer;
	
	public class GameModule extends Sprite implements IClear
	{
		private var WIDTH:int;
		private var HEIGHT:int;
		
		public var decart:Sprite;
		
		private var ground:DisplayObject;
		private var entityLayer:Sprite;
		private var leftCup:Cup;
		private var rightCup:Cup;
		private var lavaLine:DisplayObject;
		private var lavaLineFront:DisplayObject;
		
		private static var keys:Array = [];
		
		
		private var spatialController:SpatialController;
		
		public function GameModule(room:RoomDef = null)
		{
			super();
			
			WIDTH = PopUpManager.instance.WIDTH;
			HEIGHT = PopUpManager.instance.HEIGHT;
			
			decart = new Sprite();
			addChild(decart);
			
			decart.x = 380;
			decart.y = 500;
			
			if(stage)
				onAddedToStage();
			else
				addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
		}
		
		
		public function clear():void
		{
			removeEventListener(Event.ENTER_FRAME, onTick);
			
			if(spatialController)
				spatialController.clear();
			
			if(stage)
			{
				stage.removeEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
				stage.removeEventListener(KeyboardEvent.KEY_UP, onKeyUp);
			}
			
			keys = null;
			SocketHandler.instance.clear();
		}
		
		private function onAddedToStage(e:Event = null):void
		{
			if(e) removeEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
			
			stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
			stage.addEventListener(KeyboardEvent.KEY_UP, onKeyUp);
			
			createInterface();
			
			initilizeSocketConnection();			
		}
		
		
		
		private static const LEFT:int = 37;
		private static const RIGHT:int = 39;
		private static const UP:int = 38;
		private static const SPACE:int = 32;
		
		private function onKeyDown(e:KeyboardEvent):void
		{
			addKey(e.keyCode);
		}
		
		private function addKey(keyCode:int):void
		{
			if((keyCode == SPACE || keyCode == UP) && upKey())
				return;
			if(keyCode == LEFT && leftKey())
				return;
			if(keyCode == RIGHT && rightKey())
				return
			
			keys[keyCode] = true;
			
			if(keyCode == LEFT)
			{
				// fire LEFT
				removeKey(RIGHT);
				SocketHandler.instance.action("left");
			}
			
			if(keyCode == RIGHT)
			{
				// fire RIGHT
				removeKey(LEFT);
				SocketHandler.instance.action("right");
			}
			
			if(keyCode == SPACE || keyCode == UP)
			{
				// fire UP
				SocketHandler.instance.action("jump");
			}
		}
		
		
		
		private function onKeyUp(e:KeyboardEvent):void
		{
			removeKey(e.keyCode);
		}
		
			
		private function removeKey(keyCode:int):void
		{
			if((keyCode == SPACE || keyCode == UP) && upKey() == false)
				return;
			if(keyCode == LEFT && leftKey() == false)
				return;
			if(keyCode == RIGHT && rightKey() == false)
				return
			
			delete keys[keyCode];
			
			if(keyCode == LEFT)
			{
				// fire LEFT END
				SocketHandler.instance.action("stopX");
			}
			
			if(keyCode == RIGHT)
			{
				// fire RIGHT END
				SocketHandler.instance.action("stopX");
			}
			
			if(keyCode == SPACE || keyCode == UP)
			{
				// fire UP END
				SocketHandler.instance.action("stopY");
			}
		}
		
		
		public static function leftKey():Boolean
		{
			return keys[LEFT];
		}
		
		
		
		public static function rightKey():Boolean
		{
			return keys[RIGHT];
		}
		
		
		public static function upKey():Boolean
		{
			return keys[SPACE] || keys[UP];
		}
		
		
		
		/**
		 * Создаем весь интерфейс, который известен заранее 
		 * и может быть создан еще дло установки соединения по сокетам
		 */
		private function createInterface():void
		{
			ground = Lib.getMc("BalanceGround");
			ground.width = WIDTH;
			ground.height = HEIGHT;
			addChildAt(ground, 0);
			
			entityLayer = new Sprite();
			decart.addChild(entityLayer);
			
			lavaLine = Lib.getMc("BalanceLava");
			decart.addChildAt(lavaLine, 0);
			lavaLineFront = Object(lavaLine).front as DisplayObject;
			decart.addChild(lavaLineFront);
			lavaLine.alpha = 0;
			lavaLineFront.alpha = 0;
			
			leftCup = new Cup();
			leftCup.alpha = 0;
			decart.addChild(leftCup);
			
			rightCup = new Cup();
			rightCup.alpha = 0;
			decart.addChild(rightCup);
		}
		
		
		/**
		 * Установить соединение с сервером
		 */
		private function initilizeSocketConnection():void
		{
			startProcess();
			SocketHandler.instance.init();
		}
		
		
		/**
		 * Соединение с сервером благополучно установлено
		 * Запускаем процесс игры
		 */
		private function startProcess():void
		{
			spatialController = new SpatialController(WIDTH, HEIGHT);
			spatialController.entityLayerRef = entityLayer;
			
			leftCup.x = spatialController.leftCupRef.x;
			leftCup.y = -spatialController.leftCupRef.y;
			rightCup.x = spatialController.rightCupRef.x;
			rightCup.y = -spatialController.rightCupRef.y;
			
			lavaLine.y = lavaLineFront.y = -spatialController.lavaRef.y;
			lavaLine.x = lavaLineFront.x = -decart.x;
			
			addEventListener(Event.ENTER_FRAME, onTick);
			lastTickTime = getTimer();
			
			TweenMax.allTo([
				leftCup, 
				rightCup, 
				lavaLine, 
				lavaLineFront], 0.2, {"alpha": 1});
		}

		
		private var lastTickTime:Number;
		private function onTick(e:Event):void
		{
			var currentTime:Number = getTimer()
			var deltaTime:Number = currentTime - lastTickTime;
			
			// сначала обрабатываем чаши весов
			leftCup.y = -spatialController.leftCupRef.y;
			rightCup.y = -spatialController.rightCupRef.y;			
			
			spatialController.onTick(deltaTime);
			
			lastTickTime = getTimer();
		}
		
	}	
	
}